using DG.Tweening.Core;
using DG.Tweening.Plugins.Options;
using DG.Tweening;
using IQIGame.Onigao.Framework;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay
{
    public class TransformAgent : IReusableClass
    {
        /// <summary>
        /// 真正的Transform，记住get方法一定不能是public，否则可以绕过Agent
        /// </summary>
        public virtual Transform Value { protected get; set; }
        public virtual uint MaxStore => 500;
        public virtual bool isValueNull => false;

        #region Transform 方法实现
        public virtual Transform parent => Value.parent;
        public virtual GameObject gameObject => Value.gameObject;
        public virtual Vector3 position
        {
            get
            {
                return Value.position;
            }
            set
            {
                Value.position = value;
            }
        }

        public virtual Quaternion localRotation
        {
            get
            {
                return Value.localRotation;
            }
            set
            {
                Value.localRotation = value;
            }
        }

        public virtual Quaternion rotation
        {
            get
            {
                return Value.rotation;
            }
            set
            {
                Value.rotation = value;
            }
        }

        public virtual Vector3 forward
        {
            get
            {
                return Value.forward;
            }
            set
            {
                Value.forward = value;
            }
        }

        public virtual Vector3 eulerAngles
        {
            get
            {
                return Value.eulerAngles;
            }
            set
            {
                Value.eulerAngles = value;
            }
        }

        public virtual Transform Find(string n)
        {
            return Value.Find(n);
        }

        public virtual void SetParent(Transform parent, bool worldPositionStays = true)
        {
            Value.SetParent(parent, worldPositionStays);
        }

        public virtual void LookAt(Transform target)
        {
            Value.LookAt(target);
        }

        public virtual void LookAt(Vector3 worldPosition)
        {
            Value.LookAt(worldPosition, Vector3.up);
        }

        public virtual void LookAt(Vector3 worldPosition, Vector3 worldUp)
        {
            Value.LookAt(worldPosition, worldUp);
        }
        #endregion Transform 方法实现

        #region DOTween 扩展
        public TweenerCore<Quaternion, Quaternion, NoOptions> DORotateQuaternionSpeedBase(Quaternion endValue, float duration)
        {
            if (Value == null)
            {
                LogGame.LogError("该方法不支持transform可能为空的情况，只适用于视野范围内的动画处理，视野外的请使用update。");
                return null;
            }
            return Value.DORotateQuaternionSpeedBase(endValue, duration);
        }

        public TweenerCore<Vector3, Vector3, VectorOptions> DOMove(Vector3 endValue, float duration, bool snapping = false)
        {
            if (Value == null)
            {
                LogGame.LogError("该方法不支持transform可能为空的情况，只适用于视野范围内的动画处理，视野外的请使用update");
                return null;
            }
            return Value.DOMove(endValue, duration, snapping);
        }

        public TweenerCore<Quaternion, Quaternion, NoOptions> DORotateQuaternion(Quaternion endValue, float duration)
        {
            if (Value == null)
            {
                LogGame.LogError("该方法不支持transform可能为空的情况，只适用于视野范围内的动画处理，视野外的请使用update");
                return null;
            }
            return Value.DORotateQuaternion(endValue, duration);
        }

        public int DOKill(bool complete = false)
        {
            if (Value == null)
            {
                return 0;
            }
            return Value.DOKill(complete);
        }
        #endregion DOTween 扩展

        /// <summary>
        /// 隐转 TransformAgent -> Transform
        /// </summary>
        /// <param name="obj"></param>
        public static implicit operator Transform(TransformAgent obj)
        {
            return obj?.Value;
        }

        public virtual void OnReset()
        {
            Value = null;
        }
    }

    /// <summary>
    /// 当模型移除后，依然支持各组件继续调用Transform的属性的代理
    /// </summary>
    public class NullableTransformAgent : TransformAgent
    {
        public TViewEntity entity { get; internal set; }
        public override bool isValueNull => Value == null;

        #region Transform 方法实现
        public override Vector3 position
        {
            get
            {
                return Value ? Value.position : entity.unityPosOfData;
            }
            set
            {
                if (Value == null)
                {
                    return;
                }
                Value.position = value;
            }
        }

        public override Quaternion localRotation
        {
            get
            {
                return Value ? Value.localRotation : Quaternion.identity;
            }
            set
            {
                if (Value == null)
                {
                    return;
                }
                Value.localRotation = value;
            }
        }

        public override Quaternion rotation
        {
            get
            {
                return Value ? Value.rotation : Quaternion.identity;
            }
            set
            {
                if (Value == null)
                {
                    return;
                }
                Value.rotation = value;
            }
        }

        public override Vector3 forward
        {
            get
            {
                return Value ? Value.forward : Vector3.forward;
            }
            set
            {
                if (Value == null)
                {
                    return;
                }
                Value.forward = value;
            }
        }

        public override Vector3 eulerAngles
        {
            get
            {
                return Value ? Value.eulerAngles : Vector3.zero;
            }
            set
            {
                if (Value == null)
                {
                    return;
                }
                Value.eulerAngles = value;
            }
        }

        public override void LookAt(Transform target)
        {
            if (Value == null)
            {
                return;
            }
            Value.LookAt(target);
        }

        public override void LookAt(Vector3 worldPosition)
        {
            if (Value == null)
            {
                return;
            }
            Value.LookAt(worldPosition, Vector3.up);
        }

        public override void LookAt(Vector3 worldPosition, Vector3 worldUp)
        {
            if (Value == null)
            {
                return;
            }
            Value.LookAt(worldPosition, worldUp);
        }
        #endregion Transform 方法实现

        public override void OnReset()
        {
            base.OnReset();
            entity = null;
        }
    }
}
